package graphique;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.swing.SwingUtilities;

import modele.IntervalleTemporelle;
import modele.IntervalleTemporellesFactory;

import org.eclipse.draw2d.AbstractBorder;
import org.eclipse.draw2d.Border;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Ellipse;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.FreeformLayer;
import org.eclipse.draw2d.FreeformLayout;
import org.eclipse.draw2d.GridLayout;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.KeyEvent;
import org.eclipse.draw2d.KeyListener;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.LayoutManager;
import org.eclipse.draw2d.LightweightSystem;
import org.eclipse.draw2d.LineBorder;
import org.eclipse.draw2d.MarginBorder;
import org.eclipse.draw2d.MouseEvent;
import org.eclipse.draw2d.MouseListener;
import org.eclipse.draw2d.MouseMotionListener;
import org.eclipse.draw2d.Polyline;
import org.eclipse.draw2d.RectangleFigure;
import org.eclipse.draw2d.RoundedRectangle;
import org.eclipse.draw2d.ScrollPane;
import org.eclipse.draw2d.Shape;
import org.eclipse.draw2d.UpdateManager;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import org.eclipse.gef.editpolicies.XYLayoutEditPolicy;
import org.eclipse.gef.requests.CreateRequest;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.StructuredViewer;




class IntervalleFigure{
	IntervalleTemporelle owner;
	int jourDeLaSemaine;
	int x;
	int y;
	int hauteur;
	int largeur;
	int margeHauteLabel= 15;
	public RoundedRectangle zone;
	private Label labelHeureDebut;
	private VueEmployeJour vueEmployeJour;
	private Label labelHeureFin;
	Boolean lock = false;
	private RoundedRectangle boutonHaut;
	public IntervalleFigure(){
		 zone = new RoundedRectangle();
		 boutonHaut = new RoundedRectangle();//new Ellipse();
		 //calcul hauteur
		
	
	}
	public void draw(VueEmployeJour vueEmployeJour) {
		this.vueEmployeJour = vueEmployeJour;
		// TODO Auto-generated method stub
		zone.setBounds(new Rectangle(
				jourDeLaSemaine * ((vueEmployeJour.container.LARGEUR_JOUR_SEMAINE))+vueEmployeJour.container.MARGE_GAUCHE_JOUR_SEMAINE, 
				y,  
				(vueEmployeJour.container.LARGEUR_JOUR_SEMAINE),
				hauteur));
		zone.setAlpha(70);
		zone.setBackgroundColor(ColorConstants.red);
		vueEmployeJour.container.add(zone);
		
		boutonHaut.setBounds(new Rectangle(
				jourDeLaSemaine * ((vueEmployeJour.container.LARGEUR_JOUR_SEMAINE))+vueEmployeJour.container.MARGE_GAUCHE_JOUR_SEMAINE, 
				y,  
				this.zone.getBounds().width,
				10));
		boutonHaut.setBackgroundColor(ColorConstants.red);
		boutonHaut.setAlpha(60);
	//	boutonHaut.setBorder(new LineBorder(ColorConstants.red, 0));
		vueEmployeJour.container.add(boutonHaut);
		
		
		
		SimpleDateFormat dt1 = new SimpleDateFormat("HH:mm");
		
		labelHeureDebut = new Label(dt1.format(this.owner.debut));
		labelHeureDebut.setBounds(new Rectangle(
				this.zone.getBounds().x-(vueEmployeJour.container.LARGEUR_JOUR_SEMAINE/2)+20, 
				this.zone.getBounds().y+ margeHauteLabel,   
				(vueEmployeJour.container.LARGEUR_JOUR_SEMAINE),
				10));
		vueEmployeJour.container.add(labelHeureDebut);
		
		
		labelHeureFin = new Label(dt1.format(this.owner.fin));
		labelHeureFin.setBounds(new Rectangle(
				this.zone.getBounds().x-(vueEmployeJour.container.LARGEUR_JOUR_SEMAINE/2)+20, 
				this.zone.getBounds().y+ margeHauteLabel+15,   
				(vueEmployeJour.container.LARGEUR_JOUR_SEMAINE),
				10));
		vueEmployeJour.container.add(labelHeureFin);
		
		// draw poignet pour taille
		
		
		
	}
	
	public void setSelected() {
		LineBorder brdr = new LineBorder(ColorConstants.black, 2);
			     
		zone.setBorder(brdr);
		
		// TODO Auto-generated method stub
		
	}
	public void setUnSelected() {
		// TODO Auto-generated method stub
		LineBorder brdr = new LineBorder(ColorConstants.red, 0);
	     
		zone.setBorder(brdr);
		
	}
	public void translate(int i, int height) {
		if (this.lock) return;

		this.zone.translate(i,height);
		SimpleDateFormat dt1 = new SimpleDateFormat("HH:mm");
		
		this.labelHeureDebut.setText(dt1.format(this.owner.debut));	
		this.labelHeureDebut.setBounds(new Rectangle(
				
				this.zone.getBounds().x-(vueEmployeJour.container.LARGEUR_JOUR_SEMAINE/2)+20, 
				this.zone.getBounds().y+ margeHauteLabel,  
				(vueEmployeJour.container.LARGEUR_JOUR_SEMAINE),
				10
				));
		this.labelHeureFin.setText(dt1.format(this.owner.fin));	
		this.labelHeureFin.setBounds(new Rectangle(
				
				this.zone.getBounds().x-(vueEmployeJour.container.LARGEUR_JOUR_SEMAINE/2)+20, 
				this.zone.getBounds().y+15+ margeHauteLabel,  
				(vueEmployeJour.container.LARGEUR_JOUR_SEMAINE),
				10
				));
		boutonHaut.setBounds(new Rectangle(
				this.zone.getBounds().x, 
				this.zone.getBounds().y,  
				this.zone.getBounds().width,
				10));
		//this.labelHeureDebut.translate(i, height);
		// TODO Auto-generated method stub
		
	}
	/*protected void createContextMenuFor(StructuredViewer viewer) { 
		   MenuManager contextMenu = new MenuManager("#PopUp"); 
		   contextMenu.add(new Separator("additions")); 
		   contextMenu.setRemoveAllWhenShown(true); 
		  // contextMenu.addMenuListener(this); 
		   Menu menu= contextMenu.createContextMenu(viewer.getControl()); 
		   viewer.getControl().setMenu(menu); 
		   //getSite().registerContextMenu(contextMenu, new UnwrappingSelectionProvider(viewer)); 

		   } */
	public void setDateDebut(Date yToDate) {
		if (this.lock) return;
		// TODO Auto-generated method stub
		this.owner.debut = yToDate;
		
	}
	public void setDateFin(Date yToDate) {
		if (this.lock) return;

		// TODO Auto-generated method stub
		this.owner.fin = yToDate;
		
	}
	public void setHauteur() {
		
		// TODO Auto-generated method stub
		//Calcul hauteur en fonction différence DATE
		int res = 
				(int) ((this.owner.fin.getTime() - this.owner.debut.getTime()) / 1000 /60);  
		this.hauteur = res;
	}
	public void setLocked() {
		// TODO Auto-generated method stub
		this.lock = true;
	}
	public void setUnLocked() {
		this.lock = false;
		// TODO Auto-generated method stub
		
	}

	
}


class MargeGaucheHeure extends Figure{
	public  float heureDeb = (float) 7.0;
	public float heureFin = (float)23.5;
	private final int LARGEUR = 735; 
	
	public MargeGaucheHeure(){
		float h = (heureFin - heureDeb) * 60;
		int hauteur = (int) h+1;
		this.setSize( LARGEUR,hauteur+30 );
		
		
		for (int i = 0; i < hauteur ; i = i+60){
			int y = i + Entete.SIZE_JOUR_HAUTEUR;
			Polyline line = new Polyline();
	        line.setPoints(new PointList(new int[] { 0, y, 800, y }));
	        line.setAntialias(SWT.ON);
	        //line.setLineDash(new float[] { 5.0f, 5.0f });
	   
	        Label tH = new Label(""+(int)(heureDeb+(i/60)));
	        tH.setBackgroundColor(ColorConstants.blue);
		    tH.setBounds(new Rectangle(0, y, 30,20));
		    this.add(line);
		    this.add(tH);
		    for (int j=1; j < 4; j ++) {
		    	Polyline linedash = new Polyline();
		    	linedash.setPoints(new PointList(new int[] { 30, y+(j*15), 730, y+(j*15) }));
		    	linedash.setAntialias(SWT.ON);
		    	linedash.setLineStyle(SWT.LINE_CUSTOM);
		    	linedash.setLineDash(new float[] { 1.1f, 5.5f });
		    	this.add(linedash);
		    }
		    
		    //Draw horizontale line
		  
		    for ( int k = 30; k <  840 ; k = k+100){
		    	Polyline linedash = new Polyline();
		    	linedash.setPoints(new PointList(new int[] { k, 0, k,hauteur }));
		    	linedash.setAntialias(SWT.ON);
		    	this.add(linedash);
		    }
		   
		}
		
	}
	
	
}

class Entete extends Figure {
	
	public final static int SIZE_JOUR_HAUTEUR=20;
	private final static int SIZE_JOUR_LARGEUR=100;
	private final static Color COLOR_J_1 = ColorConstants.lightGreen;
	private final static Color COLOR_J_2 = ColorConstants.lightBlue;

	private  static enum JOUR_SEMAINE{
		Lundi,
		Mardi,
		Mercredi,
		Jeudi,
		Vendredi,
		Samedi,
		Dimanche;
		
	};
	private RectangleFigure J1;

	public Entete (){
		this.setSize(800, 20);
		int i=0;
		J1=  new RectangleFigure();
		J1.setBackgroundColor(ColorConstants.white);
	    J1.setBounds(new Rectangle(0, 0, SIZE_JOUR_LARGEUR*7, SIZE_JOUR_HAUTEUR+1));
	    this.add(J1);
	    
		for (JOUR_SEMAINE J: JOUR_SEMAINE.values()) {
			int X=(i*SIZE_JOUR_LARGEUR);
			J1=  new RectangleFigure();
			if (i%2 == 0) {
				J1.setBackgroundColor( COLOR_J_1);
			}
			else {
				J1.setBackgroundColor(COLOR_J_2);
				
			}
			J1.setAlpha(80);
		    J1.setBounds(new Rectangle(X, 0, SIZE_JOUR_LARGEUR, SIZE_JOUR_HAUTEUR+1));
		    Label tJ1 = new Label(""+J);
		    tJ1.setBounds(new Rectangle(X, 0, SIZE_JOUR_LARGEUR, SIZE_JOUR_HAUTEUR));
		    
		    this.add(J1);
		    this.add(tJ1);
		    i++;
		}
		
	}
}

class vueGantt extends Figure  implements MouseListener, MouseMotionListener,KeyListener{
	public final static int MARGE_GAUCHE_JOUR_SEMAINE=30;
	public final static int MARGE_HAUTE_HEURE_SEMAINE=20;
	public final static int LARGEUR_JOUR_SEMAINE=100;


	private Figure node1;
	private Figure node2;
	private Point location;
	private Figure entete;
	private IFigure tmp;
	//private MargeGaucheHeure MargeGaucheHeure;
	private graphique.MargeGaucheHeure margeGaucheHeure;
	public List<IntervalleFigure> listeIntervalleFigure;
	private IntervalleFigure intervalleSelected;
	private Point oldXJour;
	public Composite compositeControl;

	public vueGantt(VueEmployeJour vueEmployeJour){
		this.setSize(750, 500);
		
		
		/*node1 = new RectangleFigure();
		 node1.setBackgroundColor(ColorConstants.lightGreen);
	     node1.setBounds(new Rectangle(20, 10, 100, 20));
	   
	    node2 = new RectangleFigure();
		 node2.setBackgroundColor(ColorConstants.blue);
	     node2.setBounds(new Rectangle(400, 10, 100, 20));
	     node1.setOpaque(true);
	     node2.setOpaque(true);
	     ((Shape) node2).setAlpha(60);
		this.add(node1);
		this.add(node2);*/
		entete = new Entete();
		entete.setBounds(new Rectangle(MARGE_GAUCHE_JOUR_SEMAINE,0,entete.getSize().width,entete.getSize().height));
		
		
	
		margeGaucheHeure = new MargeGaucheHeure();
		margeGaucheHeure.setBounds(new Rectangle(0,0,margeGaucheHeure.getSize().width,margeGaucheHeure.getSize().height));
		
		this.add(margeGaucheHeure);
		this.add(entete);
		this.addMouseListener(this);
	      this.addMouseMotionListener(this);
	      this.addKeyListener(this);
	      
	     
		
	}

	@Override
	public void mouseDragged(MouseEvent arg0) {
		
		  Point newLocation= arg0.getLocation();
		  arg0.consume();
		  
		
		  if (this.intervalleSelected == null) return;
		  
		  Dimension offset = newLocation.getDifference(location);

			 UpdateManager updateMgr = this.intervalleSelected.zone.getUpdateManager();
			   LayoutManager layoutMgr = this.intervalleSelected.zone.getParent().getLayoutManager();
			   Rectangle bounds = this.intervalleSelected.zone.getBounds();
			   updateMgr.addDirtyRegion(this.intervalleSelected.zone.getParent(), bounds);
			  // bounds = bounds.getCopy().translate(offset.width, offset.height);
			  // layoutMgr.setConstraint(node1, bounds);
			   int x=0;
			   Dimension changeJour = newLocation.getDifference(this.oldXJour);
			  
			   if (changeJour.width < -this.LARGEUR_JOUR_SEMAINE) {
				   x = -this.LARGEUR_JOUR_SEMAINE;
				   this.oldXJour = newLocation;
			   }
			   if (changeJour.width > this.LARGEUR_JOUR_SEMAINE) {
				   x = this.LARGEUR_JOUR_SEMAINE;
				   this.oldXJour = newLocation;
			   }
			   this.intervalleSelected.setDateDebut(this.yToDate(this.intervalleSelected.owner.debut,  offset.height));
			  this.intervalleSelected.setDateFin(this.yToDate(this.intervalleSelected.owner.fin,offset.height));
			   this.intervalleSelected.translate(x, offset.height);

			   location=newLocation;
		  
		
	}

	@Override
	public void mouseEntered(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
		
	}

	@Override
	public void mouseExited(MouseEvent arg0) {
		// TODO Auto-generated method stub
	}

	@Override
	public void mouseHover(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseMoved(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseDoubleClicked(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mousePressed(MouseEvent arg0) {
		
		// TODO Auto-generated method stub
		 location =arg0.getLocation();
		 this.oldXJour = location;
		  //Dimension offset = location.getDifference(location);
		   
		 
		/*
		 * 
		 tmp= new RectangleFigure();
		 tmp.setBounds(node1.getBounds());
		 tmp.setBackgroundColor(node1.getBackgroundColor());
		 ((Shape) tmp).setAlpha(40);
		 this.add(tmp);
		 
		 
		 
*/		 
		  
		  //detect si on clique sur un intervalle 
		  
		 for ( IntervalleFigure intervalle :  this.listeIntervalleFigure){
			 if (!(intervalle.zone.containsPoint(location ))) continue;
			 
			 this.intervalleSelected = intervalle;
			 this.intervalleSelected.setSelected();
			if ((arg0.button == 3 ) ||
				((arg0.getState() & SWT.CONTROL) > 0)
				// Si on a pas de touche droite c'est equivalent à touche gauche + ctrl
				
					){
				
				Action actionLock =
					      new Action(
					        "&Lock",
					       ImageDescriptor.createFromFile(null, "image/ical.png")) {
					        
					      public void run() {
					        System.out.println("HOME");
					        intervalleSelected.setLocked();

					        
					      }
					    };
					    Action actionUnLock =
							      new Action(
							        "&UnLock",
							       ImageDescriptor.createFromFile(null, "image/ical.png")) {
							        
							      public void run() {
							        intervalleSelected.setUnLocked();

							        
							      }
							    };
				MenuManager menuMgr = new MenuManager("&TEST");
				
				menuMgr.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
				 menuMgr.add(actionLock);
				 menuMgr.add(actionUnLock);
				//menuMgr.cre
				
				Menu menu = menuMgr.createContextMenu(this.compositeControl);
				
				
				menu.addDisposeListener(new DisposeListener(){

					@Override
					//Ici on ferme la fenêtre 
					public void widgetDisposed(DisposeEvent e) {
						if (intervalleSelected != null ){
						 intervalleSelected.setUnSelected();
						 intervalleSelected = null;
						}
						
					}
					
				}
				);
				//menu.setLocation(location.x+this.getBounds().x,location.y+this.getBounds().y);
				menu.setVisible(true);
				
				
				
				
				
				
			}

			 
		 }
		 
		 arg0.consume();
		 
		 
		
	}

	@Override
	public void mouseReleased(MouseEvent arg0) {
		// TODO Auto-generated method stub
		//this.remove(tmp);
		if (this.intervalleSelected != null) {
		this.intervalleSelected.setUnSelected();
		}
		this.intervalleSelected = null;
		 arg0.consume();
	}

	public void setVerticalUpdate(int y) {
		
		// TODO Auto-generated method stub
		entete.setBounds(new Rectangle(MARGE_GAUCHE_JOUR_SEMAINE,y,entete.getSize().width,entete.getSize().height));

	}
	//EN fonction de l'heure et de y renvoei lheure permet de retourner l'heure en fonction du date et d'une position
	// Utiliser lors du déplacement et de l'agrandissment 
	public Date yToDate(Date date,int y) {
		// TODO Auto-generated method stub

		
		Date dateR = new Date(date.getTime() + (y * 60*1000));
		
		//float heure = (float) (c.get(Calendar.HOUR_OF_DAY)+ ( (float) (c.get(Calendar.MINUTE)) /60.0  ));
		
		//int y =((int) ((heure - this.margeGaucheHeure.heureDeb) * 60 )) +  this.MARGE_HAUTE_HEURE_SEMAINE; 
		
		return dateR;
	}
	
	public int DateToY(Date debut) {
		// TODO Auto-generated method stub
		
		Calendar c = Calendar.getInstance();
		
		c.setTime(debut);
		float heure = (float) (c.get(Calendar.HOUR_OF_DAY)+ ( (float) (c.get(Calendar.MINUTE)) /60.0  ));
		int y =((int) ((heure - this.margeGaucheHeure.heureDeb) * 60 )) +  this.MARGE_HAUTE_HEURE_SEMAINE; 
		

		return y;
	}

	@Override
	public void keyPressed(KeyEvent arg0) {
		System.out.println(arg0.keycode);
		arg0.consume();
		// TODO Auto-generated method stub
		
	}

	@Override
	public void keyReleased(KeyEvent arg0) {
		// TODO Auto-generated method stub
		
	}
	
	
	
}





public class VueEmployeJour extends Canvas {

	protected vueGantt container;
	private List<IntervalleFigure> listeIntervalleFigure;
	private List<IntervalleTemporelle> listeIntervalle;

	public VueEmployeJour(Composite parent, int style) {
		super(parent, SWT.DOUBLE_BUFFERED);
		this.listeIntervalleFigure = new ArrayList<graphique.IntervalleFigure>();
		// TODO Auto-generated constructor stub
		
		LightweightSystem lws = new LightweightSystem(this);
		container = new vueGantt(this);
		container.listeIntervalleFigure = this.listeIntervalleFigure;
		container.compositeControl = parent;
		//GanttEdit g = new GanttEdit();
		//IFigure container = g.createFigure(this);
	   
	  
        
       
        lws.setContents(container);
        
        this.setSize(800, 1100);
        
	    log.logger.Infologg("[GRAPH SCHED EMPLOYE]" + container.getSize() + this.getSize());

	     
		
	}

	

	public void setVerticalUpdate(int y) {
		// TODO Auto-generated method stub
		container.setVerticalUpdate(y);
		
	}
	
	
	public void addIntervalles(IntervalleTemporellesFactory listeIntervalle) {
		this.listeIntervalle =  listeIntervalle.intervalle;
		
		for ( IntervalleTemporelle intervalle : listeIntervalle.intervalle){
			Calendar c = Calendar.getInstance();
			c.setTime(intervalle.debut);
			//detect le jour de la semaine pour la date.
			IntervalleFigure fig = new IntervalleFigure();
			fig.owner =  intervalle;
			this.listeIntervalleFigure.add(fig);
			
			fig.x =0 ;
			fig.y=container.DateToY(intervalle.debut);
			fig.setHauteur();
			fig.largeur= 50;
			fig.jourDeLaSemaine = c.get(Calendar.DAY_OF_WEEK);
		}
		
		this.drawIntervalle();
		
		// TODO Auto-generated method stub
		
	}

	private void drawIntervalle() {
		
		for (IntervalleFigure fig : this.listeIntervalleFigure){
			fig.draw(this);
		}
		
		
		// TODO Auto-generated method stub
		
	}

	




}
